package statistics;

import datastructures.UserParameters;
import edu.rit.numeric.Statistics;

public class LOD_Contrasts extends AbstractStatisticTests implements IStatisticalTest {

	public LOD_Contrasts (UserParameters userParams) {
		super(userParams);
	}
	
	@Override
	public double TestCasesOnly(int order, int[][] observedCases) 
	{
		double z_cases = TestCasesOnly_Zscore(order, observedCases);
		double probability = Statistics.chiSquarePvalue(1, Math.pow(z_cases,2)) ; // / 2;
		return probability;
	}

	@Override
	public double TestCasesOnly_Zscore(int order, int[][] observedCases) 
	{
		double[][] obsCases = new double[2][2];
		obsCases[1][1] = Math.max(observedCases[1][1], 1);
		obsCases[1][0] = Math.max(observedCases[1][0], 1);
		obsCases[0][1] = Math.max(observedCases[0][1], 1);
		obsCases[0][0] = Math.max(observedCases[0][0], 1);
		
		// This doesn't work - severe under-dispersion
//		double[][] observedCases = new double[2][2];
//		observedCases[1][1] = obsvdCases[1][1] + 0.5;
//		observedCases[1][0] = obsvdCases[1][0] + 0.5;
//		observedCases[0][1] = obsvdCases[0][1] + 0.5;
//		observedCases[0][0] = obsvdCases[0][0] + 0.5;

		double lod_cases = Math.log( (obsCases[1][1] * obsCases[0][0] ) / ( obsCases[1][0] * obsCases[0][1] ) );
		double var_cases = // (double) 0.5 * ( 	
											( 1.0 / obsCases[1][1] ) + ( 1.0 / obsCases[1][0] ) + 
											( 1.0 / obsCases[0][1] ) + ( 1.0 / obsCases[0][0] ) 	;
										 // );

		double z_cases = lod_cases / Math.sqrt(var_cases) ;
		return z_cases;
	}

	@Override
	public double TestCasesVsControls(int order, int[][] observedCases, int[][] observedControls) 
	{
		double z_diff = TestCasesVsControls_Zscore(order, observedCases, observedControls);
		double probability = Statistics.chiSquarePvalue(1, Math.pow(z_diff,2)) ; // / 2;
		return probability;
	}

	@Override
	public double TestCasesVsControls_Zscore(int order, int[][] observedCases, int[][] observedControls) 
	{
		double[][] obsCases = new double[2][2];
		obsCases[1][1] = Math.max(observedCases[1][1], 1);
		obsCases[1][0] = Math.max(observedCases[1][0], 1);
		obsCases[0][1] = Math.max(observedCases[0][1], 1);
		obsCases[0][0] = Math.max(observedCases[0][0], 1);

		double lod_cases = Math.log( (double) ( obsCases[1][1] * obsCases[0][0] ) / ( obsCases[1][0] * obsCases[0][1] ) );
		double var_cases =  //(double) 0.5 * ( 	
											( 1.0 / obsCases[1][1] ) + ( 1.0 / obsCases[1][0] ) + 
											( 1.0 / obsCases[0][1] ) + ( 1.0 / obsCases[0][0] ) ;
										  //);

		double[][] obsControls = new double[2][2];
		obsControls[1][1] = Math.max(observedControls[1][1], 1);
		obsControls[1][0] = Math.max(observedControls[1][0], 1);
		obsControls[0][1] = Math.max(observedControls[0][1], 1);
		obsControls[0][0] = Math.max(observedControls[0][0], 1);
		
		double lod_controls = Math.log( (double) ( obsControls[1][1] * obsControls[0][0] ) / ( obsControls[1][0] * obsControls[0][1] ) );
		double var_controls =  //(double) 0.5 * ( 	
												( 1.0 / obsControls[1][1] ) + ( 1.0 / obsControls[1][0] ) + 
												( 1.0 / obsControls[0][1] ) + ( 1.0 / obsControls[0][0] ) ;
											 // );
		
		double z_contrast = ( lod_cases - lod_controls ) / Math.sqrt ( var_cases + var_controls ) ;
		return z_contrast;
	}

}
